package com.oig.sys.file.controller;


import cn.hutool.core.util.StrUtil;
import com.oig.common.exception.BadRequestException;
import com.oig.common.exception.ServiceException;
import com.oig.sys.file.dto.FileInfoDto;
import com.oig.sys.file.service.IFileUploadService;
import com.oig.sys.file.vo.UploadVo;
import com.oig.sys.minio.core.MinIOTemplate;
import com.oig.sys.minio.util.ObjectNameUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;


@Tag(name = "文件上传下载")
@Slf4j
@RestController
@RequestMapping("/file")
@RequiredArgsConstructor
public class FileUploadController {


    private final IFileUploadService fileUploadService;
    private final MinIOTemplate minIOTemplate ;

    /**
     * 接口传文件，文件转了一道，只支持小文件上传
     */
    @PostMapping("/upload")
    @Operation(summary = "上传附件列表,上传小文件用，返回fileId列表")
    public UploadVo upload(@RequestPart("file") MultipartFile file){
        if (file == null || file.getSize() == 0 || StrUtil.isBlank(file.getOriginalFilename())) {
            throw new BadRequestException("空文件");
        }
        log.info("upload file:{},{},{},{}",file.getName(),file.getContentType(),file.getSize(),file.getOriginalFilename());
        return this.fileUploadService.upload(file);
    }



    @PostMapping("/batchUpload")
    @Operation(summary = "上传附件列表,返回fileId列表")
    public List<UploadVo> upload(@RequestPart(value = "files") MultipartFile[] files){
        log.debug("批量上传文件：{}", files.length);
        return this.fileUploadService.upload(files);
    }


    @GetMapping("/download")
    @Operation(summary = "下载附件,返回ResponseEntity")
    @Parameter(name = "fileId", description = "文件的id")
    public ResponseEntity<byte[]> download(@RequestParam(name = "fileId") String fileId){
        log.info("download file:{}",fileId);
        InputStream inputStream = null;
        try{
            String oldBucket = fileId.substring(0,fileId.indexOf(ObjectNameUtil.FILE_SPLIT_PATH)) ;
            String oldObjectName = fileId.substring(fileId.indexOf(ObjectNameUtil.FILE_SPLIT_PATH)+1);
            //ObjectStat stat = this.minIOTemplate.getObjectInfo(oldBucket,oldObjectName) ;
            inputStream = this.minIOTemplate.getObject(oldBucket, oldObjectName) ;
            byte[] data = IOUtils.toByteArray(inputStream);

            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-Type", "application/octet-stream");
            headers.add("Connection", "close");
            headers.add("Accept-Ranges", "bytes");
            return new ResponseEntity<>(data, headers, HttpStatus.OK);
        } catch (Exception e){
            log.error("download file error ", e);
            throw new ServiceException("下载文件失败");
        } finally {
            IOUtils.closeQuietly(inputStream);
        }
    }

    @Operation(summary="批量下载")
    @PostMapping(value = "/batchDownLoadFile")
    public void batchDownLoadFile(@RequestBody List<FileInfoDto> fileList, HttpServletResponse response) {
        log.info("batchDownLoadFile file:{}",fileList);
        fileUploadService.batchDownLoad(fileList,response);
    }


    @GetMapping("/downloadInResponse")
    @Operation(summary = "下载附件,直接输出二进制数据")
    @Parameters({
            @Parameter(name = "fileId", description = "文件的id"),
            @Parameter(name = "fileName", description = "文件名")
    })
    public void download(@RequestParam(name ="fileId") String fileId,
                         @RequestParam(name ="fileName") String fileName,
                         HttpServletResponse response){
        log.info("download file:{}",fileId);
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try{
            String oldBucket = fileId.substring(0,fileId.indexOf(ObjectNameUtil.FILE_SPLIT_PATH)) ;
            String oldObjectName = fileId.substring(fileId.indexOf(ObjectNameUtil.FILE_SPLIT_PATH)+1);
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            outputStream = response.getOutputStream();
            inputStream = this.minIOTemplate.getObject(oldBucket, oldObjectName) ;
            IOUtils.copy(inputStream, outputStream);
        } catch (Exception e){
            log.error("download file error ", e);
            throw new ServiceException("下载文件失败");
        } finally {
            IOUtils.closeQuietly(inputStream);
            IOUtils.closeQuietly(outputStream);
        }
    }

    @PostMapping("/moveBucket")
    @Operation(summary = "文件从临时桶挪到配置的目标桶")
    @Parameters({
            @Parameter(name = "fileId", description = "文件的id"),
            @Parameter(name = "businessType", description = "业务类型"),
            @Parameter(name = "relationType", description = "关联单据类型")
    })
    public String moveBucket(@RequestParam(name ="fileId") String fileId,
                             @RequestParam(name ="businessType") String businessType,
                             @RequestParam(name ="relationType") String relationType){
        log.info("move file bucket:{}--{}--{}",fileId, businessType, relationType);
        return this.fileUploadService.moveBucket(fileId, businessType, relationType);
    }


    @PostMapping("/removeFile")
    @Operation(summary = "文件删除文件")
    @Parameter(name = "fileId", description = "文件的id")
    public void removeFile(@RequestParam(name ="fileId") String fileId){
        log.info("remove file :{}",fileId);
        this.fileUploadService.removeFile(fileId);
    }

    @PostMapping("/getDownloadUrl")
    @Operation(summary = "获取下载连接")
    @Parameter(name = "fileId", description = "文件的id")
    public String getDownloadUrl(@RequestParam(name ="fileId") String fileId){
        log.info("get download url fileId={}",fileId);
        return this.fileUploadService.getDownloadUrl(fileId);
    }

}
